
#include <iostream>


#include <cpp/string_view.hpp>

#include "catch.hpp"
template<typename T>
struct A { };

template<typename T>
bool
operator==(const A<T>&, const A<T>&) { return true; }

template<typename T>
bool
operator<(const A<T>&, const A<T>&) { return true; }

struct B { };

// char_traits specialization
namespace std
{
	template<>
	struct char_traits<A<B> >
	{
		typedef A<B> 		char_type;
		// Unsigned as wint_t in unsigned.
		typedef unsigned long  	int_type;
		typedef streampos 	pos_type;
		typedef streamoff 	off_type;
		typedef mbstate_t 	state_type;

		static void
			assign(char_type& __c1, const char_type& __c2)
		{
			__c1 = __c2;
		}

		static bool
			eq(const char_type& __c1, const char_type& __c2)
		{
			return __c1 == __c2;
		}

		static bool
			lt(const char_type& __c1, const char_type& __c2)
		{
			return __c1 < __c2;
		}

		static int
			compare(const char_type* __s1, const char_type* __s2, size_t __n)
		{
			for (size_t __i = 0; __i < __n; ++__i)
				if (!eq(__s1[__i], __s2[__i]))
					return lt(__s1[__i], __s2[__i]) ? -1 : 1;
			return 0;
		}

		static size_t
			length(const char_type* __s)
		{
			const char_type* __p = __s;
			while (__p)
				++__p;
			return (__p - __s);
		}

		static const char_type*
			find(const char_type* __s, size_t __n, const char_type& __a)
		{
			for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p)
				if (*__p == __a) return __p;
			return 0;
		}

		static char_type*
			move(char_type* __s1, const char_type* __s2, size_t __n)
		{
			return (char_type*)memmove(__s1, __s2, __n * sizeof(char_type));
		}

		static char_type*
			copy(char_type* __s1, const char_type* __s2, size_t __n)
		{
			return (char_type*)memcpy(__s1, __s2, __n * sizeof(char_type));
		}

		static char_type*
			assign(char_type* __s, size_t __n, char_type __a)
		{
			for (char_type* __p = __s; __p < __s + __n; ++__p)
				assign(*__p, __a);
			return __s;
		}

		static char_type
			to_char_type(const int_type&)
		{
			return char_type();
		}

		static int_type
			to_int_type(const char_type&) { return int_type(); }

		static bool
			eq_int_type(const int_type& __c1, const int_type& __c2)
		{
			return __c1 == __c2;
		}

		static int_type
			eof() { return static_cast<int_type>(-1); }

		static int_type
			not_eof(const int_type& __c)
		{
			return eq_int_type(__c, eof()) ? int_type(0) : __c;
		}
	};
} // namespace std




TEST_CASE("basic_string_view:capacity")
{

	bool test = true;

	cpp::basic_string_view<A<B>> str02;
	typedef cpp::basic_string_view< A<B> >::size_type size_type_o;
	size_type_o sz03;
	size_type_o sz04;

	// non-POD types: size, length, max_size, empty()
	bool b01 = str02.empty();
	REQUIRE(b01 == true);
	sz03 = str02.size();
	sz04 = str02.length();
	REQUIRE(sz03 == sz04);
	str02.data();
	sz03 = str02.size();
	sz04 = str02.length();
	REQUIRE(sz03 == sz04);

	sz03 = str02.max_size();
	REQUIRE(sz03 >= sz04);

	sz03 = str02.size();
	str02 = {};
	b01 = str02.empty();
	REQUIRE(b01 == true);
	sz04 = str02.size();
	REQUIRE(sz03 >= sz04);

}

TEST_CASE("basic_string_view:cons")

{
	bool test = true;
	typedef cpp::string_view::size_type csize_type;

	// basic_string_view()
	const cpp::string_view str00{};
	REQUIRE(str00.length() == 0);
	REQUIRE(str00.data() == nullptr);

	// basic_string_view(const char*)
	const char str_lit01[] = "rodeo beach, marin";
	const cpp::string_view str01{ str_lit01 };
	REQUIRE(str01.length() == 18);
	REQUIRE(str01.data() == str_lit01);
	const cpp::string_view str02{ "baker beach, san francisco" };
	REQUIRE(str02.length() == 26);

	// basic_string_view(const string_view&)
	cpp::string_view str04{ str01 };
	REQUIRE(str04.length() == str01.length());
	REQUIRE(str04.data() == str01.data());

	// basic_string_view(const char* s)
	csize_type len_lit01 = strlen(str_lit01);
	cpp::string_view str05{ str_lit01, len_lit01 };
	REQUIRE(str05.length() == len_lit01);
	REQUIRE(str05.data() == str_lit01);

	// basic_string_view(basic_string& s)
	std::string istr07(10, 'z');
	cpp::string_view str07{ istr07 };
	REQUIRE(str07.length() == 10);

	{

		const char* with_nulls = "This contains \0 a zero byte.";

		// These are tests to see how basic_string_view handles data with NUL
		// bytes.  Obviously basic_string_view(char*) will halt at the first one, but
		// nothing else should.
		cpp::string_view s1(with_nulls, 28);
		REQUIRE(s1.size() == 28);
		cpp::string_view s2(s1);
		REQUIRE(s2.size() == 28);

	}

	char const * s = 0;
	cpp::string_view zero_length_built_with_NULL(s, 0);

}

TEST_CASE("basic_string_view:typetest")
{

	struct T
	{
		typedef cpp::string_view String_view;
		typedef String_view::iterator iterator;
		typedef String_view::const_iterator const_iterator;

		char t(iterator f) { return *f; }
		char t(const_iterator f) const { return *f; }
	};


	cpp::string_view s("");

	T t;
	T::const_iterator i = s.begin();

	t.t(i);



#ifdef CPPNEXT_NO_USER_DEFINED_LITERAL

	using namespace cpp::literals;

	static_assert(std::is_same<decltype("Hello"_sv), cpp::string_view>::value,
		"\"Hello\"s is cpp::string_view");

	static_assert(std::is_same<decltype(u8"Hello"_sv), cpp::string_view>::value,
		"u8\"Hello\"s is cpp::string_view");

	static_assert(std::is_same<decltype(L"Hello"_sv), cpp::wstring_view>::value,
		"L\"Hello\"s is cpp::wstring_view");

	static_assert(std::is_same<decltype(u"Hello"_sv), cpp::u16string_view>::value,
		"u\"Hello\"s is cpp::u16string_view");

	static_assert(std::is_same<decltype(U"Hello"_sv), cpp::u32string_view>::value,
		"U\"Hello\"s is cpp::u32string_view");

#endif // cpp_NO_US



}

TEST_CASE("basic_string_view:operators")
{

	cpp::wstring_view 	str_0(L"costa rica");
	cpp::wstring_view 	str_1(L"costa marbella");
	cpp::wstring_view 	str_2(L"cost");
	cpp::wstring_view		str_3(L"costa ricans");
	cpp::wstring_view		str_4;

	str_4 = str_0;
	//comparisons between string_view objects
	REQUIRE(!(str_0 == str_1));
	REQUIRE(!(str_0 == str_2));
	REQUIRE(!(str_0 == str_3));
	REQUIRE(!(str_1 == str_0));
	REQUIRE(!(str_2 == str_0));
	REQUIRE(!(str_3 == str_0));
	REQUIRE(str_4 == str_0);
	REQUIRE(str_0 == str_4);

	REQUIRE(str_0 != str_1);
	REQUIRE(str_0 != str_2);
	REQUIRE(str_0 != str_3);
	REQUIRE(str_1 != str_0);
	REQUIRE(str_2 != str_0);
	REQUIRE(str_3 != str_0);
	REQUIRE(!(str_0 != str_4));
	REQUIRE(!(str_4 != str_0));

	REQUIRE(str_0 > str_1); //true cuz r>m
	REQUIRE(str_0 > str_2);
	REQUIRE(!(str_0 > str_3));
	REQUIRE(!(str_1 > str_0)); //false cuz m<r
	REQUIRE(!(str_2 > str_0));
	REQUIRE(str_3 > str_0);
	REQUIRE(!(str_0 > str_4));
	REQUIRE(!(str_4 > str_0));

	REQUIRE(!(str_0 < str_1)); //false cuz r>m
	REQUIRE(!(str_0 < str_2));
	REQUIRE(str_0 < str_3);
	REQUIRE(str_1 < str_0); //true cuz m<r
	REQUIRE(str_2 < str_0);
	REQUIRE(!(str_3 < str_0));
	REQUIRE(!(str_0 < str_4));
	REQUIRE(!(str_4 < str_0));

	REQUIRE(str_0 >= str_1); //true cuz r>m
	REQUIRE(str_0 >= str_2);
	REQUIRE(!(str_0 >= str_3));
	REQUIRE(!(str_1 >= str_0));//false cuz m<r
	REQUIRE(!(str_2 >= str_0));
	REQUIRE(str_3 >= str_0);
	REQUIRE(str_0 >= str_4);
	REQUIRE(str_4 >= str_0);

	REQUIRE(!(str_0 <= str_1));//false cuz r>m
	REQUIRE(!(str_0 <= str_2));
	REQUIRE(str_0 <= str_3);
	REQUIRE(str_1 <= str_0);//true cuz m<r
	REQUIRE(str_2 <= str_0);
	REQUIRE(!(str_3 <= str_0));
	REQUIRE(str_0 <= str_4);
	REQUIRE(str_4 <= str_0);

	//comparisons between string_view object and string_view literal
	REQUIRE(!(str_0 == L"costa marbella"));
	REQUIRE(!(str_0 == L"cost"));
	REQUIRE(!(str_0 == L"costa ricans"));
	REQUIRE(!(L"costa marbella" == str_0));
	REQUIRE(!(L"cost" == str_0));
	REQUIRE(!(L"costa ricans" == str_0));
	REQUIRE(L"costa rica" == str_0);
	REQUIRE(str_0 == L"costa rica");

	REQUIRE(str_0 != L"costa marbella");
	REQUIRE(str_0 != L"cost");
	REQUIRE(str_0 != L"costa ricans");
	REQUIRE(L"costa marbella" != str_0);
	REQUIRE(L"cost" != str_0);
	REQUIRE(L"costa ricans" != str_0);
	REQUIRE(!(L"costa rica" != str_0));
	REQUIRE(!(str_0 != L"costa rica"));

	REQUIRE(str_0 > L"costa marbella"); //true cuz r>m
	REQUIRE(str_0 > L"cost");
	REQUIRE(!(str_0 > L"costa ricans"));
	REQUIRE(!(L"costa marbella" > str_0));//false cuz m<r
	REQUIRE(!(L"cost" > str_0));
	REQUIRE(L"costa ricans" > str_0);
	REQUIRE(!(L"costa rica" > str_0));
	REQUIRE(!(str_0 > L"costa rica"));

	REQUIRE(!(str_0 < L"costa marbella"));//false cuz r>m
	REQUIRE(!(str_0 < L"cost"));
	REQUIRE(str_0 < L"costa ricans");
	REQUIRE(L"costa marbella" < str_0);//true cuz m<r
	REQUIRE(L"cost" < str_0);
	REQUIRE(!(L"costa ricans" < str_0));
	REQUIRE(!(L"costa rica" < str_0));
	REQUIRE(!(str_0 < L"costa rica"));

	REQUIRE(str_0 >= L"costa marbella");//true cuz r>m
	REQUIRE(str_0 >= L"cost");
	REQUIRE(!(str_0 >= L"costa ricans"));
	REQUIRE(!(L"costa marbella" >= str_0));//false cuz m<r
	REQUIRE(!(L"cost" >= str_0));
	REQUIRE(L"costa ricans" >= str_0);
	REQUIRE(L"costa rica" >= str_0);
	REQUIRE(str_0 >= L"costa rica");

	REQUIRE(!(str_0 <= L"costa marbella"));//false cuz r>m
	REQUIRE(!(str_0 <= L"cost"));
	REQUIRE(str_0 <= L"costa ricans");
	REQUIRE(L"costa marbella" <= str_0);//true cuz m<r
	REQUIRE(L"cost" <= str_0);
	REQUIRE(!(L"costa ricans" <= str_0));
	REQUIRE(L"costa rica" <= str_0);
	REQUIRE(str_0 <= L"costa rica");


}

TEST_CASE("basic_string_view:access")

{

	typedef cpp::string_view::size_type csize_type;
	typedef cpp::string_view::const_reference cref;
	typedef cpp::string_view::reference ref;
	csize_type csz01, csz02;

	const cpp::string_view str01("tamarindo, costa rica");
	cpp::string_view str02("41st street beach, capitola, california");
	cpp::string_view str03;

	// const_reference operator[] (size_type pos) const;
	csz01 = str01.size();
	cref cref1 = str01[csz01 - 1];
	REQUIRE(cref1 == 'a');

	// Undefined behavior at size().
	//cref cref2 = str01[csz01];
	//VERIFY( cref2 == char() );

	// const_reference at(size_type pos) const;
	csz01 = str01.size();
	cref cref3 = str01.at(csz01 - 1);
	REQUIRE(cref3 == 'a');
	try
	{
		str01.at(csz01);
		REQUIRE(false); // Should not get here, as exception thrown.
	}
	catch (std::out_of_range&)
	{
		REQUIRE(true);
	}
	catch (...)
	{
		REQUIRE(false);
	}

}
TEST_CASE("basic_string_view:access_WChar")

{

	typedef cpp::wstring_view::size_type csize_type;
	typedef cpp::wstring_view::const_reference cref;
	typedef cpp::wstring_view::reference ref;
	csize_type csz01, csz02;

	const cpp::wstring_view str01(L"tamarindo, costa rica");
	cpp::wstring_view str02(L"41st street beach, capitola, california");
	cpp::wstring_view str03;

	// const_reference operator[] (size_type pos) const;
	csz01 = str01.size();
	cref cref1 = str01[csz01 - 1];
	REQUIRE(cref1 == 'a');

	// Undefined behavior at size().
	//cref cref2 = str01[csz01];
	//VERIFY( cref2 == char() );

	// const_reference at(size_type pos) const;
	csz01 = str01.size();
	cref cref3 = str01.at(csz01 - 1);
	REQUIRE(cref3 == L'a');
	try
	{
		str01.at(csz01);
		REQUIRE(false); // Should not get here, as exception thrown.
	}
	catch (std::out_of_range&)
	{
		REQUIRE(true);
	}
	catch (...)
	{
		REQUIRE(false);
	}

}

TEST_CASE("basic_string_view:insert")

{
	typedef cpp::string_view::size_type csize_type;
	typedef cpp::string_view::const_reference cref;
	typedef cpp::string_view::reference ref;

	const cpp::string_view str01("sailing grand traverse bay\n"
		"\t\t\t    from Elk Rapids to the point reminds me of miles");

	// ostream& operator<<(ostream&, const basic_string_view&)
	std::ostringstream ostrs01;
	try
	{
		ostrs01 << str01;
		REQUIRE(ostrs01.str() == str01);
	}
	catch (std::exception& fail_)
	{
		REQUIRE(false);
	}

	cpp::string_view hello_world;
	std::cout << hello_world;


	{
		cpp::string_view foo{ "peace\0\0\0& love" };

		std::ostringstream oss1;
		oss1 << foo;
		REQUIRE(oss1.str() == foo);

		std::ostringstream oss2;
		oss2.width(20);
		oss2 << foo;
		REQUIRE(oss2.str() != foo);
		REQUIRE(oss2.str().size() == 20);

	}

}
TEST_CASE("basic_string_view:insert_char")

{

	cpp::string_view foo{ "peace\0\0\0& love" };

	std::ostringstream oss1;
	oss1 << foo;
	REQUIRE(oss1.str() == foo);

	std::ostringstream oss2;
	oss2.width(20);
	oss2 << foo;
	REQUIRE(oss2.str() != foo);
	REQUIRE(oss2.str().size() == 20);
}
TEST_CASE("basic_string_view:modifier")

{
	using namespace cpp;
	{
		cpp::string_view str0{ "olympus mons" };
		cpp::string_view::const_pointer p = str0.data();
		str0.remove_prefix(4);
		REQUIRE(str0.data() == p + 4);
		REQUIRE(str0.length() == 8);
		REQUIRE(str0 == cpp::string_view{ "pus mons" });
	}



	{
		wstring_view str0{ L"olympus mons" };
		wstring_view::const_pointer p = str0.data();
		str0.remove_prefix(4);
		REQUIRE(str0.data() == p + 4);
		REQUIRE(str0.length() == 8);
		REQUIRE(str0 == wstring_view{ L"pus mons" });
	}

	{
		string_view str0{ "olympus mons" };
		string_view::const_pointer p = str0.data();
		str0.remove_suffix(2);
		REQUIRE(str0.data() == p);
		REQUIRE(str0.length() == 10);
		REQUIRE(str0 == string_view{ "olympus mo" });


	}

	{
		wstring_view str0{ L"olympus mons" };
		wstring_view::const_pointer p = str0.data();
		str0.remove_suffix(2);
		REQUIRE(str0.data() == p);
		REQUIRE(str0.length() == 10);
		REQUIRE(str0 == wstring_view{ L"olympus mo" });
	}

}
TEST_CASE("basic_string_view:some")

{
	using namespace cpp;
	string_view s = "hello world";
	string_view s2 = "hello world2";
	string_view s3;
	auto p = s.find(string_view("l"));

	REQUIRE(p == 2u);
	REQUIRE(s < s2);

	swap(s, s2);
	REQUIRE(s > s2);

	swap(s, s2);

	REQUIRE(s.find_first_of(string_view("world")) == 2u);
	REQUIRE(s.find_last_of(string_view("world")) == 10);
	REQUIRE(s.find_first_not_of(string_view("world")) == 0);
	REQUIRE(s.find_last_not_of(string_view("world")) == 5);

	REQUIRE(s.find_first_of(string_view("x")) == string_view::npos);
	REQUIRE(s.find_last_of(string_view("x")) == string_view::npos);

	REQUIRE(s.find_first_not_of(string_view("hello world")) == string_view::npos);
	REQUIRE(s.find_last_not_of(string_view("hello world")) == string_view::npos);

	REQUIRE(s.find_first_not_of(string_view("")) == 0);
	REQUIRE(s.find_last_not_of(string_view("")) == 10);

	s.remove_prefix(6);

	REQUIRE(s == string_view("world"));

	s.remove_suffix(2);
	REQUIRE(s == string_view("wor"));

	REQUIRE(s == "wor");

	s = s3 = "hello world";

	REQUIRE(s == s3);
}

TEST_CASE("basic_string_view:compare")

{

	enum want_value { lt = 0, z = 1, gt = 2 };


	auto 	test_value = [](int result, want_value expected)
	{
		bool test = true;
		bool pass = false;

		switch (expected) {
		case lt:
			if (result < 0)
				pass = true;
			break;
		case z:
			if (!result)
				pass = true;
			break;
		case gt:
			if (result > 0)
				pass = true;
			break;
		default:
			pass = false; //should not get here
		}

		REQUIRE(pass);
		return 0;
	};

	using namespace cpp;



	{
		wstring_view 	str_0(L"costa rica");
		wstring_view 	str_1(L"costa marbella");
		wstring_view 	str_2;

		//sanity check
		test_value(wcscmp(L"costa marbella", L"costa rica"), lt);
		test_value(wcscmp(L"costa rica", L"costa rica"), z);
		test_value(wcscmp(str_1.data(), str_0.data()), lt);
		test_value(wcscmp(str_0.data(), str_1.data()), gt);
		test_value(wcsncmp(str_1.data(), str_0.data(), 6), z);
		test_value(wcsncmp(str_1.data(), str_0.data(), 14), lt);
		test_value(wmemcmp(str_1.data(), str_0.data(), 6), z);
		test_value(wmemcmp(str_1.data(), str_0.data(), 14), lt);
		test_value(wmemcmp(L"costa marbella", L"costa rica", 14), lt);

		// int compare(const basic_string_view& str) const;
		test_value(str_0.compare(str_1), gt); //because r>m
		test_value(str_1.compare(str_0), lt); //because m<r
		str_2 = str_0;
		test_value(str_2.compare(str_0), z);
		str_2 = L"cost";
		test_value(str_2.compare(str_0), lt);
		str_2 = L"costa ricans";
		test_value(str_2.compare(str_0), gt);

		// int compare(size_type pos1, size_type n1, const basic_string_view& str) const;
		test_value(str_1.compare(0, 6, str_0), lt);
		str_2 = L"cost";
		test_value(str_1.compare(0, 4, str_2), z);
		test_value(str_1.compare(0, 5, str_2), gt);

		// int compare(size_type pos1, size_type n1, const basic_string_view& str, 
		//		 size_type pos2, size_type n2) const;	
		test_value(str_1.compare(0, 6, str_0, 0, 6), z);
		test_value(str_1.compare(0, 7, str_0, 0, 7), lt);
		test_value(str_0.compare(0, 7, str_1, 0, 7), gt);

		// int compare(const charT* s) const;
		test_value(str_0.compare(L"costa marbella"), gt);
		test_value(str_1.compare(L"costa rica"), lt);
		str_2 = str_0;
		test_value(str_2.compare(L"costa rica"), z);
		test_value(str_2.compare(L"cost"), gt);
		test_value(str_2.compare(L"costa ricans"), lt);

		// int compare(size_type pos, size_type n1, const charT* str,
		//             size_type n2 = npos) const;
		test_value(str_1.compare(0, 6, L"costa rica", 0, 6), z);
		test_value(str_1.compare(0, 7, L"costa rica", 0, 7), lt);
		test_value(str_0.compare(0, 7, L"costa marbella", 0, 7), gt);
	}

	{
		string_view 	str_0("costa rica");
		string_view 	str_1("costa marbella");
		string_view 	str_2;

		//sanity check
		test_value(strcmp("costa marbella", "costa rica"), lt);
		test_value(strcmp("costa rica", "costa rica"), z);
		test_value(strcmp(str_1.data(), str_0.data()), lt);
		test_value(strcmp(str_0.data(), str_1.data()), gt);
		test_value(strncmp(str_1.data(), str_0.data(), 6), z);
		test_value(strncmp(str_1.data(), str_0.data(), 14), lt);
		test_value(memcmp(str_1.data(), str_0.data(), 6), z);
		test_value(memcmp(str_1.data(), str_0.data(), 14), lt);
		test_value(memcmp("costa marbella", "costa rica", 14), lt);

		// int compare(const basic_string_view& str) const;
		test_value(str_0.compare(str_1), gt); //because r>m
		test_value(str_1.compare(str_0), lt); //because m<r
		str_2 = str_0;
		test_value(str_2.compare(str_0), z);
		str_2 = "cost";
		test_value(str_2.compare(str_0), lt);
		str_2 = "costa ricans";
		test_value(str_2.compare(str_0), gt);

		// int compare(size_type pos1, size_type n1, const basic_string_view& str) const;
		test_value(str_1.compare(0, 6, str_0), lt);
		str_2 = "cost";
		test_value(str_1.compare(0, 4, str_2), z);
		test_value(str_1.compare(0, 5, str_2), gt);

		// int compare(size_type pos1, size_type n1, const basic_string_view& str, 
		//		 size_type pos2, size_type n2) const;	
		test_value(str_1.compare(0, 6, str_0, 0, 6), z);
		test_value(str_1.compare(0, 7, str_0, 0, 7), lt);
		test_value(str_0.compare(0, 7, str_1, 0, 7), gt);

		// int compare(const charT* s) const;
		test_value(str_0.compare("costa marbella"), gt);
		test_value(str_1.compare("costa rica"), lt);
		str_2 = str_0;
		test_value(str_2.compare("costa rica"), z);
		test_value(str_2.compare("cost"), gt);
		test_value(str_2.compare("costa ricans"), lt);

		// int compare(size_type pos, size_type n1, const charT* str,
		//             size_type n2 = npos) const;
		test_value(str_1.compare(0, 6, "costa rica", 0, 6), z);
		test_value(str_1.compare(0, 7, "costa rica", 0, 7), lt);
		test_value(str_0.compare(0, 7, "costa marbella", 0, 7), gt);
	}

	{

		const char lit_01[]{ 'w', 'e', '\0', 'r', 'd' };
		const char lit_02[]{ 'w', 'e', 'i', '\0', 'd' };

		const char lit_ref_a[]{ 'w', 'e', '\0', 'q', 'd' };
		const string_view str_a(lit_ref_a, 5);
		REQUIRE(str_a.compare(0, 5, lit_01, 5) < 0);

		const char lit_ref_b[]{ 'w', 'e', 'i' };
		const string_view str_b(lit_ref_b, 3);
		REQUIRE(str_b.compare(0, 3, lit_02, 5) < 0);

	}
}

TEST_CASE("basic_string_view:copy")

{
	{
		const char str_lit01[] = "123456789A";
		const cpp::string_view str01(str_lit01);
		char buffer[4] = { 0 };

		auto len = str01.copy(buffer, sizeof(buffer), 8);
		REQUIRE(2 == len);
		REQUIRE('9' == buffer[0]);
	}

	{
		typedef cpp::wstring_view::size_type csize_type;
		csize_type csz01;

		const wchar_t str_lit01[] = L"123456789A";
		const cpp::wstring_view str01(str_lit01);
		wchar_t buffer[4] = { 0 };

		csize_type len = str01.copy(buffer, sizeof(buffer), 8);
		REQUIRE(2 == len);
		REQUIRE(L'9' == buffer[0]);
	}
}
TEST_CASE("basic_string_view:data")

{
	{
		cpp::string_view empty;

		REQUIRE(empty.size() == 0);
		const cpp::string_view::value_type* p = empty.data();
		REQUIRE(p == nullptr);
	}
	{
		cpp::wstring_view empty;

		REQUIRE(empty.size() == 0);
		const cpp::wstring_view::value_type* p = empty.data();
		REQUIRE(p == nullptr);
	}
}
TEST_CASE("basic_string_view:to_string")

{
	const char str_lit[] = "123456789A";
	const cpp::string_view sv(str_lit);
	char buffer[4] = { 0 };

	auto s1 = sv.to_string();
	REQUIRE(s1 == str_lit);

	auto s2 = sv.to_string(std::allocator<char>{});
	static_assert(std::is_same<decltype(s2)::allocator_type, std::allocator<char> >::value,
		"to_string() uses custom allocator");
	REQUIRE(std::equal(s1.begin(), s1.end(), s2.begin()));
	auto s3 = static_cast<std::string>(sv);
	REQUIRE(s3 == s1);
}
TEST_CASE("basic_string_view:find")

{
	{
		typedef cpp::string_view::size_type csize_type;
		typedef cpp::string_view::const_reference cref;
		typedef cpp::string_view::reference ref;
		csize_type npos = cpp::string_view::npos;
		csize_type csz01, csz02;

		const char str_lit01[] = "mave";
		const cpp::string_view str01("mavericks, santa cruz");
		cpp::string_view str02(str_lit01);
		cpp::string_view str03("s, s");
		cpp::string_view str04;

		// size_type find(const string_view&, size_type pos = 0) const;
		csz01 = str01.find(str01);
		REQUIRE(csz01 == 0);
		csz01 = str01.find(str01, 4);
		REQUIRE(csz01 == npos);
		csz01 = str01.find(str02, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find(str02, 3);
		REQUIRE(csz01 == npos);
		csz01 = str01.find(str03, 0);
		REQUIRE(csz01 == 8);
		csz01 = str01.find(str03, 3);
		REQUIRE(csz01 == 8);
		csz01 = str01.find(str03, 12);
		REQUIRE(csz01 == npos);

		// An empty string_view consists of no characters
		// therefore it should be found at every point in a string_view,
		// except beyond the end
		csz01 = str01.find(str04, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find(str04, 5);
		REQUIRE(csz01 == 5);
		csz01 = str01.find(str04, str01.size());
		REQUIRE(csz01 == str01.size());
		csz01 = str01.find(str04, str01.size() + 1);
		REQUIRE(csz01 == npos);

		// size_type find(const char* s, size_type pos, size_type n) const;
		csz01 = str01.find(str_lit01, 0, 3);
		REQUIRE(csz01 == 0);
		csz01 = str01.find(str_lit01, 3, 0);
		REQUIRE(csz01 == 3);

		// size_type find(const char* s, size_type pos = 0) const;
		csz01 = str01.find(str_lit01);
		REQUIRE(csz01 == 0);
		csz01 = str01.find(str_lit01, 3);
		REQUIRE(csz01 == npos);

		// size_type find(char c, size_type pos = 0) const;
		csz01 = str01.find('z');
		csz02 = str01.size() - 1;
		REQUIRE(csz01 == csz02);
		csz01 = str01.find('/');
		REQUIRE(csz01 == npos);
	}

	{

		typedef cpp::string_view::size_type csize_type;
		csize_type npos = cpp::string_view::npos;
		csize_type csz01, csz02;

		const char str_lit01[] = "mave";
		const cpp::string_view str01("mavericks, santa cruz");
		cpp::string_view str02(str_lit01);
		cpp::string_view str03("s, s");
		cpp::string_view str04;

		// size_type find_first_of(const string_view&, size_type pos = 0) const;
		cpp::string_view str05("xena rulez");
		csz01 = str01.find_first_of(str01);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_of(str01, 4);
		REQUIRE(csz01 == 4);
		csz01 = str01.find_first_of(str02, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_of(str02, 3);
		REQUIRE(csz01 == 3);
		csz01 = str01.find_first_of(str03, 0);
		REQUIRE(csz01 == 8);
		csz01 = str01.find_first_of(str03, 3);
		REQUIRE(csz01 == 8);
		csz01 = str01.find_first_of(str03, 12);
		REQUIRE(csz01 == 16);
		csz01 = str01.find_first_of(str05, 0);
		REQUIRE(csz01 == 1);
		csz01 = str01.find_first_of(str05, 4);
		REQUIRE(csz01 == 4);

		// An empty string_view consists of no characters
		// therefore it should be found at every point in a string_view,
		// except beyond the end
		// However, str1.find_first_of(str2,pos) finds the first character in 
		// str1 (starting at pos) that exists in str2, which is none for empty str2
		csz01 = str01.find_first_of(str04, 0);
		REQUIRE(csz01 == npos);
		csz01 = str01.find_first_of(str04, 5);
		REQUIRE(csz01 == npos);

		// size_type find_first_of(const char* s, size_type pos, size_type n) const;
		csz01 = str01.find_first_of(str_lit01, 0, 3);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_of(str_lit01, 3, 0);
		REQUIRE(csz01 == npos);

		// size_type find_first_of(const char* s, size_type pos = 0) const;
		csz01 = str01.find_first_of(str_lit01);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_of(str_lit01, 3);
		REQUIRE(csz01 == 3);

		// size_type find_first_of(char c, size_type pos = 0) const;
		csz01 = str01.find_first_of('z');
		csz02 = str01.size() - 1;
		REQUIRE(csz01 == csz02);

	}

	{

		typedef cpp::string_view::size_type csize_type;
		csize_type npos = cpp::string_view::npos;
		csize_type csz01;

		const cpp::string_view str01("Bob Rock, per me");
		const char str_lit01[] = "Bob Rock";
		cpp::string_view str02("ovvero Trivi");
		cpp::string_view str03(str_lit01);
		cpp::string_view str04;

		// size_type find_first_not_of(const string_view&, size_type pos = 0) const;
		csz01 = str01.find_first_not_of(str01);
		REQUIRE(csz01 == npos);
		csz01 = str01.find_first_not_of(str02, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_not_of(str02, 10);
		REQUIRE(csz01 == 10);
		csz01 = str01.find_first_not_of(str02, 12);
		REQUIRE(csz01 == 14);
		csz01 = str01.find_first_not_of(str03, 0);
		REQUIRE(csz01 == 8);
		csz01 = str01.find_first_not_of(str03, 15);
		REQUIRE(csz01 == 15);
		csz01 = str01.find_first_not_of(str03, 16);
		REQUIRE(csz01 == npos);
		csz01 = str01.find_first_not_of(str04, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_not_of(str04, 12);
		REQUIRE(csz01 == 12);
		csz01 = str03.find_first_not_of(str01, 0);
		REQUIRE(csz01 == npos);
		csz01 = str04.find_first_not_of(str02, 0);
		REQUIRE(csz01 == npos);

		// size_type find_first_not_of(const char* s, size_type pos, size_type n) const;
		csz01 = str01.find_first_not_of(str_lit01, 0, 0);
		REQUIRE(csz01 == 0);
		csz01 = str01.find_first_not_of(str_lit01, 0, 8);
		REQUIRE(csz01 == 8);
		csz01 = str01.find_first_not_of(str_lit01, 10, 0);
		REQUIRE(csz01 == 10);

		// size_type find_first_not_of(const char* s, size_type pos = 0) const;
		csz01 = str01.find_first_not_of(str_lit01);
		REQUIRE(csz01 == 8);
		csz01 = str02.find_first_not_of(str_lit01, 2);
		REQUIRE(csz01 == 2);

		// size_type find_first_not_of(char c, size_type pos = 0) const;
		csz01 = str01.find_first_not_of('B');
		REQUIRE(csz01 == 1);
		csz01 = str01.find_first_not_of('o', 1);
		REQUIRE(csz01 == 2);
		csz01 = str02.find_first_not_of('z');
		REQUIRE(csz01 == 0);
		csz01 = str04.find_first_not_of('S');
		REQUIRE(csz01 == npos);
	}

	{

		typedef cpp::string_view::size_type csize_type;
		csize_type npos = cpp::string_view::npos;

		cpp::string_view use = "anu";
		csize_type pos1 = use.find("a", npos);

		REQUIRE(pos1 == npos);
	}

}
TEST_CASE("basic_string_view:rfind")

{
	typedef cpp::string_view::size_type csize_type;
	typedef cpp::string_view::const_reference cref;
	typedef cpp::string_view::reference ref;
	csize_type npos = cpp::string_view::npos;
	csize_type csz01, csz02;

	const char str_lit01[] = "mave";
	const cpp::string_view str01("mavericks, santa cruz");
	cpp::string_view str02(str_lit01);
	cpp::string_view str03("s, s");
	cpp::string_view str04;

	// size_type rfind(const string_view&, size_type pos = 0) const;
	csz01 = str01.rfind(str01);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str01, 4);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str02, 3);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str02);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str03);
	REQUIRE(csz01 == 8);
	csz01 = str01.rfind(str03, 3);
	REQUIRE(csz01 == npos);
	csz01 = str01.rfind(str03, 12);
	REQUIRE(csz01 == 8);

	// An empty string_view consists of no characters
	// therefore it should be found at every point in a string_view,
	// except beyond the end
	csz01 = str01.rfind(str04, 0);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str04, 5);
	REQUIRE(csz01 == 5);
	csz01 = str01.rfind(str04, str01.size());
	REQUIRE(csz01 == str01.size());
	csz01 = str01.rfind(str04, str01.size() + 1);
	REQUIRE(csz01 == str01.size());

	// size_type rfind(const char* s, size_type pos, size_type n) const;
	csz01 = str01.rfind(str_lit01, 0, 3);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str_lit01, 3, 0);
	REQUIRE(csz01 == 3);

	// size_type rfind(const char* s, size_type pos = 0) const;
	csz01 = str01.rfind(str_lit01);
	REQUIRE(csz01 == 0);
	csz01 = str01.rfind(str_lit01, 3);
	REQUIRE(csz01 == 0);

	// size_type rfind(char c, size_type pos = 0) const;
	csz01 = str01.rfind('z');
	csz02 = str01.size() - 1;
	REQUIRE(csz01 == csz02);
	csz01 = str01.rfind('/');
	REQUIRE(csz01 == npos);




	{

		cpp::string_view z("ab");
		cpp::string_view::size_type pos;
		pos = z.find_last_of("ab");
		REQUIRE(pos == 1);
		pos = z.find_last_of("Xa");
		REQUIRE(pos == 0);
		pos = z.find_last_of("Xb");
		REQUIRE(pos == 1);
		pos = z.find_last_of("XYZ");
		REQUIRE(pos == cpp::string_view::npos);
		pos = z.find_last_of('a');
		REQUIRE(pos == 0);
		pos = z.find_last_of('b');
		REQUIRE(pos == 1);
		pos = z.find_last_of('X');
		REQUIRE(pos == cpp::string_view::npos);

		pos = z.find_last_of('a', 0);
		REQUIRE(pos == 0);
		pos = z.find_last_of('a', 1);
		REQUIRE(pos == 0);
		pos = z.find_last_of('b', 0);
		REQUIRE(pos == cpp::string_view::npos);
		pos = z.find_last_of('b', 1);
		REQUIRE(pos == 1);

		pos = z.find_last_of("a", 0);
		REQUIRE(pos == 0);

		pos = z.find_last_of("a", 1);
		REQUIRE(pos == 0);

		pos = z.find_last_of("b", 0);
		REQUIRE(pos == cpp::string_view::npos);
		pos = z.find_last_of("b", 1);
		REQUIRE(pos == 1);

	}

	{
		typedef cpp::string_view::size_type csize_type;
		cpp::string_view::size_type pos;
		csize_type npos = cpp::string_view::npos;

		cpp::string_view x;
		pos = x.find_last_not_of('X');
		REQUIRE(pos == npos);
		pos = x.find_last_not_of("XYZ");
		REQUIRE(pos == npos);

		cpp::string_view y("a");
		pos = y.find_last_not_of('X');
		REQUIRE(pos == 0);
		pos = y.find_last_not_of('a');
		REQUIRE(pos == npos);
		pos = y.find_last_not_of("XYZ");
		REQUIRE(pos == 0);
		pos = y.find_last_not_of("a");
		REQUIRE(pos == npos);

		cpp::string_view z("ab");
		pos = z.find_last_not_of('X');
		REQUIRE(pos == 1);
		pos = z.find_last_not_of("XYZ");
		REQUIRE(pos == 1);
		pos = z.find_last_not_of('b');
		REQUIRE(pos == 0);
		pos = z.find_last_not_of("Xb");
		REQUIRE(pos == 0);
		pos = z.find_last_not_of("Xa");
		REQUIRE(pos == 1);


	}
}


TEST_CASE("basic_string_view:substr")

{

	typedef cpp::string_view::size_type csize_type;
	typedef cpp::string_view::const_reference cref;
	typedef cpp::string_view::reference ref;
	csize_type csz01;

	const char str_lit01[] = "rockaway, pacifica";
	const cpp::string_view str01(str_lit01);
	cpp::string_view str02;

	// basic_string_view<charT, _Traits, _Alloc>
	//  substr(size_type pos = 0, size_type n = npos) const;
	csz01 = str01.size();
	str02 = str01.substr(0, 1);
	REQUIRE(str02 == "r");
	str02 = str01.substr(10);
	REQUIRE(str02 == "pacifica");

	try
	{
		str02 = str01.substr(csz01 + 1);
		REQUIRE(false);
	}
	catch (std::out_of_range&)
	{
		REQUIRE(true);
	}
	catch (...)
	{
		REQUIRE(false);
	}

	try
	{
		str02 = str01.substr(csz01);
		REQUIRE(str02.size() == 0);
		REQUIRE(str02.begin() == str01.end());
		REQUIRE(true);
	}
	catch (...)
	{
		REQUIRE(false);
	}
}



/************************************************************************
*from boost::string_view
************************************************************************/



namespace
{

	typedef cpp::string_view string_view;

	//  Should be equal
	void interop(const std::string &str, string_view ref) {
		//  REQUIRE ( str == ref );
		REQUIRE(str.size() == ref.size());
		REQUIRE(std::equal(str.begin(), str.end(), ref.begin()));
		REQUIRE(std::equal(str.rbegin(), str.rend(), ref.rbegin()));
	}

	void null_tests(const char *p) {
		//  All zero-length string-refs should be equal
		string_view sr1; // NULL, 0
		string_view sr2(NULL, 0);
		string_view sr3(p, 0);
		string_view sr4(p);

		REQUIRE(sr1 == sr2);
		REQUIRE(sr1 == sr3);
		REQUIRE(sr2 == sr3);
	}

	//  make sure that substrings work just like strings
	void test_substr(const std::string &str) {
		const size_t sz = str.size();
		string_view ref(str);

		//  Substrings at the end
		for (size_t i = 0; i <= sz; ++i)
			interop(str.substr(i), ref.substr(i));

		//  Substrings at the beginning
		for (size_t i = 0; i <= sz; ++i)
			interop(str.substr(0, i), ref.substr(0, i));

		//  All possible substrings
		for (size_t i = 0; i < sz; ++i)
			for (size_t j = i; j < sz; ++j)
				interop(str.substr(i, j), ref.substr(i, j));
	}

	//  make sure that removing prefixes and suffixes work just like strings
	void test_remove(const std::string &str) {
		const size_t sz = str.size();
		std::string work;
		string_view ref;

		for (size_t i = 1; i <= sz; ++i) {
			work = str;
			ref = str;
			while (ref.size() >= i) {
				interop(work, ref);
				work.erase(0, i);
				ref.remove_prefix(i);
			}
		}

		for (size_t i = 1; i < sz; ++i) {
			work = str;
			ref = str;
			while (ref.size() >= i) {
				interop(work, ref);
				work.erase(work.size() - i, i);
				ref.remove_suffix(i);
			}
		}
	}

	const char *test_strings[] = {
		"",
		"1",
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
		"0123456789",
		NULL
	};

}




TEST_CASE("boost::basic_string_view:test1")
{
	const char **p = &test_strings[0];

	while (*p != NULL) {
		interop(*p, *p);
		test_substr(*p);
		test_remove(*p);
		null_tests(*p);

		p++;
	}


}

namespace
{

	typedef cpp::string_view string_view;

	void reverse(const char *arg) {
		//  Round trip
		string_view sr1(arg);
		std::string string1(sr1.rbegin(), sr1.rend());
		string_view sr2(string1);
		std::string string2(sr2.rbegin(), sr2.rend());

		REQUIRE(std::equal(sr2.rbegin(), sr2.rend(), arg));
		REQUIRE(string2 == arg);
		REQUIRE(std::equal(sr1.begin(), sr1.end(), string2.begin()));
	}

	//	This helper function eliminates signed vs. unsigned warnings
	string_view::size_type ptr_diff(const char *res, const char *base)
	{
		REQUIRE(res >= base);
		return static_cast<string_view::size_type> (res - base);
	}

	void find(const char *arg) 
	{
		string_view sr1;
		string_view sr2;
		const char *p;

		//  Look for each character in the string(searching from the start)
		p = arg;
		sr1 = arg;
		while (*p) {
			string_view::size_type pos = sr1.find(*p);
			REQUIRE((pos != string_view::npos && (pos <= ptr_diff(p, arg))));
			++p;
		}

		//  Look for each character in the string (searching from the end)
		p = arg;
		sr1 = arg;
		while (*p) {
			string_view::size_type pos = sr1.rfind(*p);
			REQUIRE((pos != string_view::npos && pos < sr1.size() && (pos >= ptr_diff(p, arg))));
			++p;
		}

		//	Look for pairs on characters (searching from the start)
		sr1 = arg;
		p = arg;
		while (*p && *(p + 1)) {
			string_view sr3(p, 2);
			string_view::size_type pos = sr1.find(sr3);
			REQUIRE((pos != string_view::npos && pos <= static_cast<string_view::size_type>(p - arg)));
			p++;
		}

		sr1 = arg;
		p = arg;
		//  for all possible chars, see if we find them in the right place.
		//  Note that strchr will/might do the _wrong_ thing if we search for NULL
		for (int ch = 1; ch < 256; ++ch) {
			string_view::size_type pos = sr1.find(ch);
			const char *strp = std::strchr(arg, ch);
			REQUIRE((strp == NULL) == (pos == string_view::npos));
			if (strp != NULL)
				REQUIRE(ptr_diff(strp, arg) == pos);
		}

		sr1 = arg;
		p = arg;
		//  for all possible chars, see if we find them in the right place.
		//  Note that strchr will/might do the _wrong_ thing if we search for NULL
		for (int ch = 1; ch < 256; ++ch) {
			string_view::size_type pos = sr1.rfind(ch);
			const char *strp = std::strrchr(arg, ch);
			REQUIRE((strp == NULL) == (pos == string_view::npos));
			if (strp != NULL)
				REQUIRE(ptr_diff(strp, arg) == pos);
		}


		//  Find everything at the start
		p = arg;
		sr1 = arg;
		while (!sr1.empty()) {
			string_view::size_type pos = sr1.find(*p);
			REQUIRE(pos == 0);
			sr1.remove_prefix(1);
			++p;
		}

		//  Find everything at the end
		sr1 = arg;
		p = arg + std::strlen(arg) - 1;
		while (!sr1.empty()) {
			string_view::size_type pos = sr1.rfind(*p);
			REQUIRE(pos == sr1.size() - 1);
			sr1.remove_suffix(1);
			--p;
		}

		//  Find everything at the start
		sr1 = arg;
		p = arg;
		while (!sr1.empty()) {
			string_view::size_type pos = sr1.find_first_of(*p);
			REQUIRE(pos == 0);
			sr1.remove_prefix(1);
			++p;
		}


		//  Find everything at the end
		sr1 = arg;
		p = arg + std::strlen(arg) - 1;
		while (!sr1.empty()) {
			string_view::size_type pos = sr1.find_last_of(*p);
			REQUIRE(pos == sr1.size() - 1);
			sr1.remove_suffix(1);
			--p;
		}

		//  Basic sanity checking for "find_first_of / find_first_not_of"
		sr1 = arg;
		sr2 = arg;
		while (!sr1.empty()) {
			REQUIRE(sr1.find_first_of(sr2) == 0);
			REQUIRE(sr1.find_first_not_of(sr2) == string_view::npos);
			sr1.remove_prefix(1);
		}

		p = arg;
		sr1 = arg;
		while (*p) {
			string_view::size_type pos1 = sr1.find_first_of(*p);
			string_view::size_type pos2 = sr1.find_first_not_of(*p);
			REQUIRE((pos1 != string_view::npos && pos1 < sr1.size() && pos1 <= ptr_diff(p, arg)));
			if (pos2 != string_view::npos) {
				for (size_t i = 0; i < pos2; ++i)
					REQUIRE(sr1[i] == *p);
				REQUIRE(sr1[pos2] != *p);
			}

			REQUIRE(pos2 != pos1);
			++p;
		}

		//  Basic sanity checking for "find_last_of / find_last_not_of"
		sr1 = arg;
		sr2 = arg;
		while (!sr1.empty()) {
			REQUIRE(sr1.find_last_of(sr2) == (sr1.size() - 1));
			REQUIRE(sr1.find_last_not_of(sr2) == string_view::npos);
			sr1.remove_suffix(1);
		}

		p = arg;
		sr1 = arg;
		while (*p) {
			string_view::size_type pos1 = sr1.find_last_of(*p);
			string_view::size_type pos2 = sr1.find_last_not_of(*p);
			REQUIRE((pos1 != string_view::npos && pos1 < sr1.size() && pos1 >= ptr_diff(p, arg)));
			REQUIRE((pos2 == string_view::npos || pos1 < sr1.size()));
			if (pos2 != string_view::npos) {
				for (size_t i = sr1.size() - 1; i > pos2; --i)
					REQUIRE(sr1[i] == *p);
				REQUIRE(sr1[pos2] != *p);
			}

			REQUIRE(pos2 != pos1);
			++p;
		}

	}


	void to_string(const char *arg) {
		string_view sr1;
		std::string str1;
		std::string str2;

		str1.assign(arg);
		sr1 = arg;
		//	str2 = sr1.to_string<std::allocator<char> > ();
		str2 = sr1.to_string();
		REQUIRE(str1 == str2);

		std::string str3 = static_cast<std::string> (sr1);
		REQUIRE(str1 == str3);
	}

	void compare(const char *arg) {
		string_view sr1;
		std::string str1;
		std::string str2 = str1;

		str1.assign(arg);
		sr1 = arg;
		REQUIRE(sr1 == sr1);	    // compare string_view and string_view
		REQUIRE(sr1 == str1);	// compare string and string_view
		REQUIRE(str1 == sr1);	// compare string_view and string
		REQUIRE(sr1 == arg);	// compare string_view and pointer
		REQUIRE(arg == sr1);	// compare pointer and string_view

		if (sr1.size() > 0) {
			(*str1.rbegin())++;
			REQUIRE(sr1 != str1);
			REQUIRE(str1 != sr1);
			REQUIRE(sr1 < str1);
			REQUIRE(sr1 <= str1);
			REQUIRE(str1 > sr1);
			REQUIRE(str1 >= sr1);

			(*str1.rbegin()) -= 2;
			REQUIRE(sr1 != str1);
			REQUIRE(str1 != sr1);
			REQUIRE(sr1 > str1);
			REQUIRE(sr1 >= str1);
			REQUIRE(str1 < sr1);
			REQUIRE(str1 <= sr1);
		}
	}

	const char *test_strings2[] = {
		"",
		"0",
		"abc",
		"AAA",  // all the same
		"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
		"abc\0asdfadsfasf",
		NULL
	};

}
TEST_CASE("boost::basic_string_view:test2")

{
	const char **p = &test_strings2[0];

	while (*p != NULL) {
		reverse(*p);
		find(*p);
		to_string(*p);
		compare(*p);
		p++;
	}
}

